﻿
package extremefx.modules.css {
	import extremefx.drawing.Color;
	import extremefx.tools.StringUtils;
	
	import flash.filters.BitmapFilterQuality;
	import flash.filters.DropShadowFilter;
	import flash.text.Font;
	import flash.utils.Dictionary;		

	/**
	 * @author Marcelo Volmaro
	 */
	public final class ComputedStyle {
		private const _cachedTextStyles:Dictionary = new Dictionary();
		private static var _availableFonts:Object;
		
		private var _fullName:String;
		private var _name:String;
		private var _pseudo:String;
		private var _value:Object;
		
		private var _styleSheet:StyleSheet;
		private var _node:IDomNode;
		
		public function ComputedStyle(pName:String, pValue:Object, pStyleSheet:StyleSheet, pNode:IDomNode) {
			_fullName = pName;
			var parts:Array = pName.split(":");
			_name = parts[0];
			_pseudo = parts[1];
			_value = pValue;
			
			_styleSheet = pStyleSheet;
			_node = pNode;
			
			if (!_availableFonts){
				var f:Object = {};
				var f2:Array = Font.enumerateFonts(true); 
				for each(var font:Font in f2){
					f[font.fontName.toLowerCase()] = font.fontName;
				}
				
				_availableFonts = f;
			}
		}
		
		public function get fullName():String{
			return _fullName;
		}
		
		public function get name():String{
			return _name;
		}
		
		public function get pseudoName():String{
			return _pseudo;
		}
		
		public function get value():Object{
			return _value;
		}
		
		public function getPseudoStyle(pPseudo:String):ComputedStyle {
			return _styleSheet.getComputedStyle(_node, pPseudo);
		}

		public function getTextStyle():XTextFormat {
			if (_cachedTextStyles[fullName]) return _cachedTextStyles[fullName];
			
			var format:XTextFormat = new XTextFormat();
			var style:Object = value;
			
			if (style.fontFamily) format.font = _getFont(style.fontFamily);
			if (style.fontSize) format.size = style.fontSize;
			if (style.color) format.color = Color.parse(style.color).toRgb();
			if (style.textAlign) format.align = style.textAlign;
			if (style.fontWeight) format.bold = parseInt(style.fontWeight) > 600;
			if (style.fontStyle) format.italic = (style.fontStyle == "italic" || style.fontStyle == "oblique");
			if (style.lineHeight) format.leading = parseFloat(style.lineHeight);
			if (style.letterSpacing) format.letterSpacing = parseFloat(style.letterSpacing);
			if (style.textDecoration) format.underline = (style.textDecoration == "underline");
			
			if (style.antiAliasType) format.antiAliasType = style.antiAliasType;
			if (style.gridFitType) format.gridFitType = style.gridFitType;
			if (style.embedFonts) format.embedFonts = (style.embedFonts == "embed");
			
//			if (style.left) format.offset.x = style.left;
//			if (style.top) format.offset.y = style.top;
			if (style.verticalAlign) format.vAlign = style.verticalAlign;
			
			if (style.textShadow && style.textShadow.length){
				var shadows:Array = [];			
				
				for each(var obj:Object in style.textShadow){
					var color:Color = new Color(Number(format.color) | 0xff000000);
					var offsetX:Number, offsetY:Number, blur:Number;
					
					offsetX = offsetY = blur = 0;
						
					for (var prop:String in obj){
						var value:String = obj[prop];
						
						switch (prop){
							case "color":
								color = Color.parse(value);
								continue;
								
							case "top":
								offsetX = parseFloat(value);
								continue;
								
							case "left":
								offsetY = parseFloat(value);
								continue;
								
							case "blur":
								blur = parseFloat(value);
						}
					}
					
					var s:DropShadowFilter = new DropShadowFilter(
						Math.sqrt(offsetX * offsetX + offsetY * offsetY),
						Math.atan2(offsetY, offsetX) * 180 / Math.PI, 
						color.toRgb(),
						color.alpha/255,
						blur,
						blur,
						1,
						BitmapFilterQuality.HIGH
					);
					
					shadows.push(s);
				}
				
				format.filters = shadows;
			}
			
			_cachedTextStyles[fullName] = format;
			return format;
		}
		
		private function _getFont(pFontFamily:Array):String {
			var af:Object = _availableFonts, name:String;
			
			for each (var cFont:String in pFontFamily){
				name = StringUtils.trim(cFont).toLowerCase();
				
				if (af[name]) 
					return af[name];
			}
			
			return null;
		}
	}
}
